package com.smart.community.commons.utils;

import cn.dev33.satoken.stp.StpUtil;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 安全工具类
 * 
 * 严格按照《智慧社区微服务架构总览.md》要求实现：
 * - 使用MD5进行密码加密和验证
 * - 严禁使用Spring Security、BCrypt等组件
 * - 提供UUID生成和随机密码生成功能
 * - 集成Sa-Token框架的Token管理功能
 * - 完全使用Sa-Token获取用户信息，移除UserContext依赖
 * 
 * @author Wu.Liang
 * @version 3.0.0
 * @updated 2025-01-30 - 移除UserContext依赖，完全使用Sa-Token
 */
public class SecurityUtils {

    private static final Logger log = LoggerFactory.getLogger(SecurityUtils.class);

    /**
     * 生成MD5哈希
     * 
     * 根据架构总览要求，使用MD5进行密码加密和验证
     * 严禁使用BCryptPasswordEncoder等Spring Security组件
     * 
     * @param input 输入字符串
     * @return MD5哈希值
     * @throws RuntimeException 当MD5算法不可用时抛出
     */
    public static String md5(String input) {
        if (input == null || input.trim().isEmpty()) {
            throw new IllegalArgumentException("输入字符串不能为空");
        }
        
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] hash = md.digest(input.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte b : hash) {
                sb.append(String.format("%02x", b & 0xff));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5算法不可用", e);
        } catch (Exception e) {
            throw new RuntimeException("MD5加密失败", e);
        }
    }

    /**
     * 验证密码
     * 
     * 使用MD5验证密码是否正确
     * 
     * @param inputPassword 用户输入的密码
     * @param storedPassword 数据库中存储的密码
     * @return 密码是否匹配
     */
    public static boolean verifyPassword(String inputPassword, String storedPassword) {
        if (inputPassword == null || storedPassword == null) {
            return false;
        }
        return md5(inputPassword).equals(storedPassword);
    }

    /**
     * 加密密码
     * 
     * 使用MD5加密密码，用于存储到数据库
     * 
     * @param password 明文密码
     * @return 加密后的密码
     */
    public static String encryptPassword(String password) {
        if (password == null || password.trim().isEmpty()) {
            throw new IllegalArgumentException("密码不能为空");
        }
        return md5(password);
    }

    /**
     * 生成UUID（去除横线）
     * 
     * @return 32位UUID字符串
     */
    public static String generateUUID() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 生成随机密码
     * 
     * @param length 密码长度
     * @return 随机密码
     */
    public static String generateRandomPassword(int length) {
        if (length <= 0) {
            throw new IllegalArgumentException("密码长度必须大于0");
        }
        
        String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int index = (int) (Math.random() * chars.length());
            sb.append(chars.charAt(index));
        }
        return sb.toString();
    }

    /**
     * 生成带特殊字符的随机密码
     * 
     * @param length 密码长度
     * @return 包含特殊字符的随机密码
     */
    public static String generateStrongRandomPassword(int length) {
        if (length <= 0) {
            throw new IllegalArgumentException("密码长度必须大于0");
        }
        
        String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int index = (int) (Math.random() * chars.length());
            sb.append(chars.charAt(index));
        }
        return sb.toString();
    }

    // ==================== Sa-Token集成方法 ====================

    /**
     * 用户登录并返回Token
     * 
     * 使用Sa-Token框架进行用户登录
     * 
     * @param userId 用户ID
     * @return Token值
     */
    public static String login(Long userId) {
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        StpUtil.login(userId);
        return StpUtil.getTokenValue();
    }

    /**
     * 获取当前登录用户ID
     * 
     * 根据"智慧社区微服务架构总览.md"的架构设计：
     * - 优先使用Sa-Token获取用户信息
     * - 如果Sa-Token中没有，尝试从请求头获取（网关注入的用户信息）
     * - 移除UserContext依赖，统一使用Sa-Token
     * 
     * @return 当前登录用户ID，未登录时返回null
     */
    public static Long getCurrentUserId() {
        try {
            // 首先尝试从Sa-Token获取
            if (StpUtil.isLogin()) {
                Object loginId = StpUtil.getLoginId();
                if (loginId != null) {
                    Long userId = null;
                    if (loginId instanceof Long) {
                        userId = (Long) loginId;
                    } else if (loginId instanceof String) {
                        try {
                            userId = Long.valueOf((String) loginId);
                        } catch (NumberFormatException e) {
                            log.warn("Sa-Token loginId转换失败，loginId: {}", loginId, e);
                        }
                    }
                    if (userId != null) {
                        log.debug("从Sa-Token获取用户ID成功: {}", userId);
                        return userId;
                    }
                }
            }
            
            // 如果Sa-Token中没有，尝试从请求头获取（网关注入的用户信息）
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                String userIdHeader = request.getHeader("X-User-Id");
                if (userIdHeader != null && !userIdHeader.trim().isEmpty()) {
                    try {
                        Long userId = Long.valueOf(userIdHeader.trim());
                        log.debug("从请求头获取用户ID成功: {}", userId);
                        return userId;
                    } catch (NumberFormatException e) {
                        log.warn("请求头X-User-Id转换失败: {}", userIdHeader, e);
                    }
                }
                
                // 调试日志：记录所有用户相关的请求头
                log.debug("请求头用户信息: X-User-Id={}, X-User-Name={}, X-User-Type={}", 
                    request.getHeader("X-User-Id"),
                    request.getHeader("X-User-Name"),
                    request.getHeader("X-User-Type"));
            }
            
            log.warn("无法获取当前用户ID: Sa-Token未登录，请求头中无用户信息");
            return null;
        } catch (Exception e) {
            log.warn("获取当前用户ID失败", e);
            return null;
        }
    }

    /**
     * 检查是否已登录
     * 
     * @return 是否已登录
     */
    public static boolean isLogin() {
        return StpUtil.isLogin();
    }

    /**
     * 用户登出
     */
    public static void logout() {
        StpUtil.logout();
    }

    /**
     * 获取当前Token值
     * 
     * @return Token值
     */
    public static String getTokenValue() {
        return StpUtil.getTokenValue();
    }

    /**
     * 检查Token是否有效
     * 
     * @param token Token值
     * @return Token是否有效
     */
    public static boolean isValidToken(String token) {
        if (token == null || token.trim().isEmpty()) {
            return false;
        }
        try {
            // 这里需要根据实际情况实现Token验证逻辑
            // 可以使用Sa-Token的StpUtil.checkLogin()方法
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 获取用户权限列表
     * 
     * @return 权限列表
     */
    public static java.util.List<String> getPermissionList() {
        try {
            // 从Sa-Token Session中获取权限列表
            Object permissionList = StpUtil.getSession().get("permissionList");
            if (permissionList instanceof java.util.List) {
                return (java.util.List<String>) permissionList;
            }
            return new java.util.ArrayList<>();
        } catch (Exception e) {
            return new java.util.ArrayList<>();
        }
    }

    /**
     * 获取用户角色列表
     * 
     * @return 角色列表
     */
    public static java.util.List<String> getRoleList() {
        try {
            // 从Sa-Token Session中获取角色列表
            Object roleList = StpUtil.getSession().get("roleList");
            if (roleList instanceof java.util.List) {
                return (java.util.List<String>) roleList;
            }
            return new java.util.ArrayList<>();
        } catch (Exception e) {
            return new java.util.ArrayList<>();
        }
    }

    /**
     * 检查是否有指定权限
     * 
     * @param permission 权限标识
     * @return 是否有权限
     */
    public static boolean hasPermission(String permission) {
        try {
            // 从Sa-Token Session中检查权限
            java.util.List<String> permissions = getPermissionList();
            return permissions.contains(permission);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 检查是否有指定角色
     * 
     * @param role 角色标识
     * @return 是否有角色
     */
    public static boolean hasRole(String role) {
        try {
            // 从Sa-Token Session中检查角色
            java.util.List<String> roles = getRoleList();
            return roles.contains(role);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 获取当前用户名
     * 
     * 根据《智慧社区微服务架构总览.md》要求：
     * - 完全使用Sa-Token获取用户信息
     * - 移除UserContext依赖
     * 
     * @return 当前登录用户名，未登录时返回null
     */
    public static String getCurrentUsername() {
        try {
            if (StpUtil.isLogin()) {
                Object loginId = StpUtil.getLoginId();
                return loginId != null ? loginId.toString() : null;
            }
            return null;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取当前用户角色
     * 
     * 根据《智慧社区微服务架构总览.md》要求：
     * - 完全使用Sa-Token获取用户信息
     * - 移除UserContext依赖
     * 
     * @return 当前登录用户角色，未登录时返回null
     */
    public static String getCurrentUserRole() {
        try {
            if (StpUtil.isLogin()) {
                java.util.List<String> roles = getRoleList();
                return roles != null && !roles.isEmpty() ? String.join(",", roles) : null;
            }
            return null;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取当前用户类型
     * 
     * 根据《智慧社区微服务架构总览.md》要求：
     * - 完全使用Sa-Token获取用户信息
     * - 移除UserContext依赖
     * 
     * @return 当前登录用户类型，未登录时返回null
     */
    public static String getCurrentUserType() {
        try {
            if (StpUtil.isLogin()) {
                // 从Sa-Token Session中获取用户类型
                Object userType = StpUtil.getSession().get("userType");
                return userType != null ? userType.toString() : null;
            }
            return null;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取当前用户权限
     * 
     * 根据《智慧社区微服务架构总览.md》要求：
     * - 完全使用Sa-Token获取用户信息
     * - 移除UserContext依赖
     * 
     * @return 当前登录用户权限集合，未登录时返回空集合
     */
    public static java.util.Set<String> getCurrentUserPermissions() {
        try {
            if (StpUtil.isLogin()) {
                java.util.List<String> permissions = getPermissionList();
                return new java.util.HashSet<>(permissions);
            }
            return new java.util.HashSet<>();
        } catch (Exception e) {
            return new java.util.HashSet<>();
        }
    }

    /**
     * 获取当前用户昵称
     * 
     * 根据《智慧社区微服务架构总览.md》要求：
     * - 完全使用Sa-Token获取用户信息
     * - 移除UserContext依赖
     * 
     * @return 当前登录用户昵称，未登录时返回null
     */
    public static String getCurrentNickname() {
        try {
            if (StpUtil.isLogin()) {
                // 从Sa-Token Session中获取用户昵称
                Object nickname = StpUtil.getSession().get("nickname");
                return nickname != null ? nickname.toString() : null;
            }
            return null;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取当前社区ID
     * 
     * 根据《智慧社区微服务架构总览.md》要求：
     * - 完全使用Sa-Token获取用户信息
     * - 移除UserContext依赖
     * 
     * @return 当前社区ID，未设置时返回null
     */
    public static Long getCurrentCommunityId() {
        try {
            if (StpUtil.isLogin()) {
                // 从Sa-Token Session中获取社区ID
                Object communityId = StpUtil.getSession().get("communityId");
                return communityId != null ? Long.valueOf(communityId.toString()) : null;
            }
            return null;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取当前物业公司ID
     * 
     * 根据《智慧社区微服务架构总览.md》要求：
     * - 完全使用Sa-Token获取用户信息
     * - 移除UserContext依赖
     * 
     * @return 当前物业公司ID，未设置时返回null
     */
    public static Long getCurrentPropertyCompanyId() {
        try {
            if (StpUtil.isLogin()) {
                // 从Sa-Token Session中获取物业公司ID
                Object propertyCompanyId = StpUtil.getSession().get("propertyCompanyId");
                return propertyCompanyId != null ? Long.valueOf(propertyCompanyId.toString()) : null;
            }
            return null;
        } catch (Exception e) {
            return null;
        }
    }
}
